/**
 * DescribesInstances.java
 * ************************** 
 * @date Jun 1, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package infrastructureAPI.algorithms.instanceTools;

import gossipServices.basic.nodeDescriptors.GeneralNodeDescriptor;
import gossipServices.basic.nodeDescriptors.NodeDescriptor;
import gossipServices.bootstraping.tman.TManService;
import infrastructureAPI.APIResponse;
import infrastructureAPI.GeneralNaiveAPIResponse;
import infrastructureAPI.Requester;
import infrastructureAPI.Service;
import infrastructureAPI.APIMessages.GeneralResponseMessage;
import infrastructureAPI.APIMessages.RequestMessage;
import infrastructureAPI.APIMessages.ResponseMessage;
import infrastructureAPI.algorithms.GeneralAPIFunctionAlgorithm;
import infrastructureAPI.backendGate.APIScript;
import infrastructureAPI.backendGate.SharedAPIParameters;

import java.net.InetAddress;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Vector;

import networkRmi.NetworkManager;

import systems.network.NetworkSystemsAPI;

/**
 * Description: 
 * Function describing a node belonging to a subcloud.
 * It returns the subcloud id and the neighbors of
 * the current node. 
 * If the contacted node doesn't belong to any subcloud
 * an exception is packed and sent to the node requester. 
 *
 */
public class DescribesInstances extends GeneralAPIFunctionAlgorithm
	implements APIScript{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 
	 */
	public DescribesInstances() { }

	/**
	 * @param requester
	 */
	public DescribesInstances(Requester requester) {
		super(requester);
	}

	@Override
	public RequestMessage createRequestMessage(InetAddress targetAddress,
			String targetNodeName) {
		return defaultRequestMessageComposition(targetAddress, targetNodeName);
	}

	@Override
	public Service extractServiceToDeRegister() {
		return null;
	}

	@Override
	public Service extractSuppliedService() {
		return null;
	}

	@Override
	public boolean requireSystemDeRegistration() {
		return false;
	}

	@Override
	public boolean requireSystemRegistration() {
		return false;
	}

	@Override
	public List<Class<?>> requiredServices() {
		List<Class<?>> list = new Vector<Class<?>>();
		list.add(NetworkManager.class);
		list.add(NetworkSystemsAPI.class);
		list.add(TManService.class);
		return list;
	}

	@Override
	public int mandatoryParametersNumber() {
		return 0;
	}

	@Override
	public String showUsage() {
		String ret = new String("");
		ret += "describe-instances ";
		ret += SharedAPIParameters.SUBCLOUD_ID_OPTION + "<subcloudID> ";
		ret += "\n";
		ret += SharedAPIParameters.SUBCLOUD_ID_OPTION +": "+
			SharedAPIParameters.SUBCLOUD_ID_OPTION_DESCRIPTION;		
		return ret;
	}

	@Override
	public boolean requireReply() {
		return true;
	}


	@Override
	public void run() {
		// retrieve Service(s)
		// --------------------------------------------------
		NetworkManager netMan = (NetworkManager) services.get(0);
		NetworkSystemsAPI netManSys = (NetworkSystemsAPI) services.get(1);
		TManService tman = (TManService) services.get(2);
		
		// composing local node NodeDescriptor
		// --------------------------------------------------
		NodeDescriptor localNode = new GeneralNodeDescriptor(netMan.getNodeName());
		
		// compose an answer message for the Requester
		// --------------------------------------------------
		String s = "LocalNode: \""+ localNode.getNodeName()+"\" belongs to "; 
		s += "subcloud: \""+ tman.getSubcloudID()+"\" with ";
		s += "neighbors:\n"+ tman.getOverlayNeighbors();
		APIResponse responseBody = new GeneralNaiveAPIResponse(s); 
		ResponseMessage respMsg = new GeneralResponseMessage(localNode, requester, responseBody);
		
		try {
			// contacting the Requester node
			// --------------------------------------------------
			netManSys.contactRemoteService(requester.getNodeAddress(), 
					requester.getPort(), requester.getRegisteredService(), respMsg);
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		}
		
		returnValue = true;
	}

}
